
package com.shop.cloud.weixin.admin.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shop.cloud.common.core.constant.CommonConstants;
import com.shop.cloud.common.core.util.R;
import com.shop.cloud.common.log.annotation.SysLog;
import com.shop.cloud.common.security.annotation.Inside;
import com.shop.cloud.common.security.entity.BaseUser;
import com.shop.cloud.common.security.util.SecurityUtils;
import com.shop.cloud.weixin.admin.config.open.WxComponentConfigProperties;
import com.shop.cloud.weixin.admin.config.open.WxOpenConfiguration;
import com.shop.cloud.weixin.common.constant.WxReturnCode;
import com.shop.cloud.weixin.admin.service.WxAppService;
import com.shop.cloud.weixin.admin.config.mp.WxMpConfiguration;
import com.shop.cloud.weixin.common.dto.WxAppSetNickNameDTO;
import com.shop.cloud.weixin.common.entity.WxApp;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.open.api.WxOpenMaService;
import me.chanjar.weixin.open.api.WxOpenMpService;
import me.chanjar.weixin.open.bean.ma.WxFastMaCategory;
import me.chanjar.weixin.open.bean.result.WxFastMaAccountBasicInfoResult;
import me.chanjar.weixin.open.bean.result.WxFastMaBeenSetCategoryResult;
import me.chanjar.weixin.open.bean.result.WxOpenResult;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信账号配置
 *
 * @author
 * @date 2019-03-23 21:26:35
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wxapp")
@Tag(description = "wxapp", name = "微信账号配置")
public class WxAppController {

	private final WxAppService wxAppService;

	private final WxComponentConfigProperties wxComponentConfigProperties;

	/**
	 * 分页查询
	 *
	 * @param page  分页对象
	 * @param wxApp 微信账号配置
	 * @return
	 */
	@Operation(summary = "分页查询")
	@GetMapping("/page")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:index','wxma:wxapp:index')")
	public R getWxAppPage(Page page, WxApp wxApp) {
		return R.ok(wxAppService.page(page, Wrappers.query(wxApp)));
	}

	/**
	 * list查询
	 * @param wxApp
	 * @return
	 */
	@Operation(summary = "list查询")
	@GetMapping("/list")
	public List<WxApp> list(WxApp wxApp) {
		return wxAppService.list(Wrappers.query(wxApp).lambda().orderByAsc(WxApp::getSort));
	}

	/**
	 * 通过id查询微信账号配置
	 *
	 * @param id
	 * @return R
	 */
	@Operation(summary = "通过id查询微信账号配置")
	@GetMapping("/{id}")
//	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:get')")
	public R getById(@PathVariable("id") String id){
		WxApp wxApp = wxAppService.getById(id);
		if(CommonConstants.YES.equals(wxApp.getIsComponent())){
			//获取第三方平台服务商AppId
			wxApp.setComponentAppId(wxComponentConfigProperties.getAppId());
		}
		return R.ok(wxApp);
	}

	/**
	 * 新增微信账号配置
	 *
	 * @param wxApp 微信账号配置
	 * @return R
	 */
	@Operation(summary = "新增微信账号配置")
	@SysLog("新增微信账号配置")
	@PostMapping
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:add','wxma:wxapp:add')")
	public R save(@RequestBody WxApp wxApp) {
		if(StrUtil.isBlank(wxApp.getShopId())){
			wxApp.setShopId(null);
		}
		BaseUser baseUser = SecurityUtils.getUser();
		if(CommonConstants.USER_TYPE_2.equals(baseUser.getType())){//店员
			wxApp.setShopId(baseUser.getShopId());
		}
		return R.ok(wxAppService.save(wxApp));
	}

	/**
	 * 修改微信账号配置
	 *
	 * @param wxApp 微信账号配置
	 * @return R
	 */
	@Operation(summary = "修改微信账号配置")
	@SysLog("修改微信账号配置")
	@PutMapping
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit','wxma:wxapp:edit')")
	public R updateById(@RequestBody WxApp wxApp) {
		if(StrUtil.isBlank(wxApp.getShopId())){
			wxApp.setShopId(null);
		}
		BaseUser baseUser = SecurityUtils.getUser();
		if(CommonConstants.USER_TYPE_2.equals(baseUser.getType())){//店员
			wxApp.setShopId(baseUser.getShopId());
		}
		wxAppService.updateById(wxApp);
		return R.ok();
	}

	/**
	 * 通过id删除微信账号配置
	 *
	 * @param id
	 * @return R
	 */
	@Operation(summary = "通过id删除微信账号配置")
	@SysLog("删除微信账号配置")
	@DeleteMapping("/{id}")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:del','wxma:wxapp:del')")
	public R removeById(@PathVariable String id) {
		return R.ok(wxAppService.removeById(id));
	}

	@Operation(summary = "生成公众号二维码")
	@SysLog("生成公众号二维码")
	@GetMapping("/qrCode")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:index')")
	public R getQrCode(String id, String sceneStr) throws WxErrorException {
		WxMpQrcodeService wxMpQrcodeService = WxMpConfiguration.getMpService(id).getQrcodeService();
		WxMpQrCodeTicket wxMpQrCodeTicket = wxMpQrcodeService.qrCodeCreateLastTicket(sceneStr);
		return R.ok(wxMpQrCodeTicket.getUrl());
	}

	@Operation(summary = "生成并保存公众号二维码")
	@SysLog("生成并保存公众号二维码")
	@PostMapping("/qrCode")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:index')")
	public R createQrCode(@RequestBody Map<String,String> param) throws WxErrorException {
		String id = param.get("id");
		String sceneStr = param.get("sceneStr");
		WxMpQrcodeService wxMpQrcodeService = WxMpConfiguration.getMpService(id).getQrcodeService();
		WxMpQrCodeTicket wxMpQrCodeTicket = wxMpQrcodeService.qrCodeCreateLastTicket(sceneStr);
		WxApp wxApp = new WxApp();
		wxApp.setId(id);
		wxApp.setQrCode(wxMpQrCodeTicket.getUrl());
		return R.ok(wxAppService.updateById(wxApp));

	}

	@Operation(summary = "微信接口次数进行清零")
	@SysLog("微信接口次数进行清零")
	@PutMapping("/quota")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:index','wxma:wxapp:index')")
	public R clearQuota(@RequestBody WxApp wxApp) {
		try {
			WxMpService wxMpService = WxMpConfiguration.getMpService(wxApp.getId());
			wxMpService.clearQuota(wxApp.getId());
			return new R<>();
		} catch (WxErrorException e) {
			e.printStackTrace();
			log.error("微信接口次数进行清零失败appID:" + wxApp.getId() + ":" + e.getMessage());
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 获取access-token
	 * @param wxApp
	 * @return
	 */
	@Operation(summary = "获取access-token")
	@GetMapping("/access-token")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:index','wxma:wxapp:index')")
	public R getAccessToken(WxApp wxApp) {
		try {
			WxMpService wxMpService = WxMpConfiguration.getMpService(wxApp.getId());
			return R.ok(wxMpService.getAccessToken());
		} catch (WxErrorException e) {
			e.printStackTrace();
			log.error("获取access-token失败appID:" + wxApp.getId() + ":" + e.getMessage());
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 获取jsapi-ticket
	 * @param wxApp
	 * @return
	 */
	@Operation(summary = "获取jsapi-ticket")
	@GetMapping("/jsapi-ticket")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:index','wxma:wxapp:index')")
	public R getJsapiTicket(WxApp wxApp) {
		try {
			WxMpService wxMpService = WxMpConfiguration.getMpService(wxApp.getId());
			return R.ok(wxMpService.getJsapiTicket());
		} catch (WxErrorException e) {
			e.printStackTrace();
			log.error("获取jsapi-ticket失败appID:" + wxApp.getId() + ":" + e.getMessage());
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 通过id查询微信账号配置
	 *
	 * @param id
	 * @return R
	 */
	@Operation(summary = "通过id查询微信账号配置")
	@Inside
	@GetMapping("/inside/{id}")
	public R getByIdInside(@PathVariable("id") String id) {
		WxApp wxApp = wxAppService.findByAppId(id);
		if(wxApp != null ){
			if(CommonConstants.YES.equals(wxApp.getIsComponent())){
				//获取第三方平台服务商AppId
				wxApp.setComponentAppId(wxComponentConfigProperties.getAppId());
			}
			wxApp.setAesKey(null);
			wxApp.setSecret(null);
			wxApp.setToken(null);
		}
		return R.ok(wxApp);
	}

	@Operation(summary = "设置名称")
	@SysLog("设置名称")
	@PostMapping("/nickname")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit','wxma:wxapp:edit')")
	public R setNickName(@RequestBody WxAppSetNickNameDTO wxAppSetNickNameDTO){
		wxAppService.setNickName(wxAppSetNickNameDTO);
		return R.ok();
	}

	@Operation(summary = "修改功能介绍")
	@SysLog("修改功能介绍")
	@PostMapping("/signature")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit','wxma:wxapp:edit')")
	public R setSignature(@RequestBody WxApp wxApp){
		wxAppService.setSignature(wxApp);
		return R.ok();
	}

	@Operation(summary = "修改头像")
	@SysLog("修改头像")
	@PostMapping("/logo")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit','wxma:wxapp:edit')")
	public R setLogo(@RequestBody WxApp wxApp){
		wxAppService.setLogo(wxApp);
		return R.ok();
	}

	/**
	 * 通过id查询搜索设置
	 *
	 * @param id
	 * @return R
	 */
	@Operation(summary = "通过id查询搜索设置")
	@GetMapping("/searchstatus/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R getSearchStatus(@PathVariable("id") String id) {
		try {
			String responseContent = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).get("https://api.weixin.qq.com/wxa/getwxasearchstatus", null);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			return R.ok(jsonObject);
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 通过id查询修改搜索设置
	 *
	 * @param id
	 * @return R
	 */
	@Operation(summary = "通过id修改搜索设置")
	@PostMapping("/searchstatus/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R setSearchStatus(@PathVariable("id") String id, @RequestBody Map<String, Object> map) {
		try {
			String responseContent = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).post("https://api.weixin.qq.com/wxa/changewxasearchstatus", map);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			String errCode = jsonObject.getStr("errcode");
			if(WxReturnCode.SUC_0.getCode().equals(errCode)){
				return R.ok(jsonObject);
			}else {
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 获取基本信息
	 *
	 * @param id
	 * @return R
	 */
	@Operation(summary = "获取基本信息")
	@GetMapping("/basicinfo/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R getBasicInfo(@PathVariable("id") String id) {
		try {
			WxFastMaAccountBasicInfoResult wxFastMaAccountBasicInfoResult = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).getBasicService().getAccountBasicInfo();
			return R.ok(wxFastMaAccountBasicInfoResult);
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 获取已设置的所有类目
	 * @param id
	 * @return
	 */
	@Operation(summary = "获取已设置的所有类目")
	@GetMapping("/category/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R getCategory(@PathVariable("id") String id) {
		try {
			WxFastMaBeenSetCategoryResult wxFastMaBeenSetCategoryResult = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).getBasicService().getCategory();
			return R.ok(wxFastMaBeenSetCategoryResult);
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	@Operation(summary = "删除类目")
	@DeleteMapping("/category/{id}/{first}/{second}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R delCategory(@PathVariable("id") String id, @PathVariable("first") int first, @PathVariable("second") int second) {
		try {
			WxOpenResult wxOpenResult = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).getBasicService().deleteCategory(first, second);
			if(!WxReturnCode.SUC_0.getCode().equals(wxOpenResult.getErrcode())){
				return R.failed(wxOpenResult.getErrmsg());
			}
			return R.ok(wxOpenResult);
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	@Operation(summary = "添加类目")
	@PostMapping("/category/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R addCategory(@PathVariable("id") String id, @RequestBody List<WxFastMaCategory> categoryList) {
		try {
			WxOpenResult wxOpenResult = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).getBasicService().addCategory(categoryList);
			if(!WxReturnCode.SUC_0.getCode().equals(wxOpenResult.getErrcode())){
				return R.failed(wxOpenResult.getErrmsg());
			}
			return R.ok(wxOpenResult);
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 获取可以设置的所有类目
	 * @param id
	 * @return
	 */
	@Operation(summary = "获取可以设置的所有类目")
	@GetMapping("/allcategorys/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R getAllCategorys(@PathVariable("id") String id) {
		try {
			String string = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id).getBasicService().getAllCategories();
			JSONObject jsonObject = JSONUtil.parseObj(string);
			String errCode = jsonObject.getStr("errcode");
			if(WxReturnCode.SUC_0.getCode().equals(errCode)){
				return R.ok(jsonObject.getJSONObject("categories_list"));
			}else {
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 获取公众号关联的小程序
	 * @param id
	 * @return
	 */
	@Operation(summary = "获取公众号关联的小程序")
	@GetMapping("/wxamplink/{id}")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit')")
	public R getWxMalink(@PathVariable("id") String id) {
		try {
			WxOpenMpService wxOpenMpService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMpServiceByAppid(id);
			Map<String, Object> map = new HashMap<>();
			String responseContent = wxOpenMpService.post("https://api.weixin.qq.com/cgi-bin/wxopen/wxamplinkget", map);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			String errCode = jsonObject.getStr("errcode");
			if(WxReturnCode.SUC_0.getCode().equals(errCode)){
				return R.ok(jsonObject.getJSONObject("wxopens"));
			}else {
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 解除已关联的小程序
	 * @param id
	 * @param map
	 * @return
	 */
	@Operation(summary = "解除已关联的小程序")
	@PostMapping("/wxampunlink/{id}")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit')")
	public R wxMaUnlink(@PathVariable("id") String id, @RequestBody Map<String, Object> map) {
		try {
			WxOpenMpService wxOpenMpService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMpServiceByAppid(id);
			String responseContent = wxOpenMpService.post("https://api.weixin.qq.com/cgi-bin/wxopen/wxampunlink", map);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			String errCode = jsonObject.getStr("errcode");
			if(WxReturnCode.SUC_0.getCode().equals(errCode)){
				return R.ok(jsonObject.getJSONObject("wxopens"));
			}else {
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 关联小程序
	 * @param id
	 * @param map
	 * @return
	 */
	@Operation(summary = "关联小程序")
	@PostMapping("/wxamplink/{id}")
	@PreAuthorize("@ato.hasAuthority('wxmp:wxapp:edit')")
	public R wxMalink(@PathVariable("id") String id, @RequestBody Map<String, Object> map) {
		try {
			WxOpenMpService wxOpenMpService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMpServiceByAppid(id);
			String responseContent = wxOpenMpService.post("https://api.weixin.qq.com/cgi-bin/wxopen/wxamplink", map);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			String errCode = jsonObject.getStr("errcode");
			if(WxReturnCode.SUC_0.getCode().equals(errCode)){
				return R.ok(jsonObject.getJSONObject("wxopens"));
			}else {
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			return WxReturnCode.wxErrorExceptionHandler(e);
		}
	}

	/**
	 * 申请开通直播
	 * @param id
	 * @param map
	 * @return
	 */
	@Operation(summary = "申请开通直播")
	@PostMapping("/applyliveinfo/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R applyLiveInfo(@PathVariable("id") String id, @RequestBody Map<String, Object> map) {
		try {
			WxOpenMaService wxOpenMaService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id);
			String responseContent = wxOpenMaService.post("https://api.weixin.qq.com/wxa/business/applyliveinfo", map);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			if(jsonObject.getInt("errcode") == 0){
				return R.ok(jsonObject);
			}else{
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			return R.failed(e.getError().getErrorMsg());
		}
	}

	/**
	 * 查询已添加的插件
	 * @param id
	 * @return
	 */
	@Operation(summary = "查询已添加的插件")
	@PostMapping("/pluginlist/{id}")
	@PreAuthorize("@ato.hasAuthority('wxma:wxapp:edit')")
	public R getPluginList(@PathVariable("id") String id, @RequestBody Map<String, Object> map) {
		try {
			WxOpenMaService wxOpenMaService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMaServiceByAppid(id);
			String responseContent = wxOpenMaService.post("https://api.weixin.qq.com/wxa/plugin", map);
			JSONObject jsonObject = JSONUtil.parseObj(responseContent);
			if(jsonObject.getInt("errcode") == 0){
				return R.ok(jsonObject);
			}else{
				return R.failed(jsonObject.getStr("errmsg"));
			}
		} catch (WxErrorException e) {
			return R.failed(JSONUtil.parseObj(e.getError().getJson()));
		}
	}
}
